package shiyl.use.any.helloworld.reflect;

import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

@Slf4j
public class HelloReflect {

    public static final void main(String[] args) {

        log.info("HelloReflect.....");

        // 模拟一个channel对象
        Channel channel = new Channel("mainChannel");

        // 模拟一个交易提案
        TransactionRequest request = new TransactionRequest();
        request.setChannelId("abschannel");
        request.setChaincode("testcc");
        request.setFunction("invoke");
        request.setArgs("{模拟一个交易提案的请求数据信息}");

        // 模拟Peer节点们
        List<Peer> peers = new ArrayList<>();
        Peer peer0 = new Peer();
        peer0.setName("peer0");
        peer0.setUrl("grcps://localhost:7050");
        peers.add(peer0);

        Peer peer1 = new Peer();
        peer1.setName("peer1");
        peer1.setUrl("grcps://localhost:7051");
        peers.add(peer1);

        Peer peer2 = new Peer();
        peer2.setName("peer2");
        peer2.setUrl("grcps://localhost:7052");
        peers.add(peer2);

        // 反射调用channel，发送交易提案
        Collection<Response> responses = reflectInvokeChannel(channel, "sendProposalTransaction" , new Class[]{TransactionRequest.class,List.class},request, peers);

        // 打印调用结果
        responses.forEach( response -> log.info(response.toString()));
    }

    // 用反射的方式调用Channel对象指定的方法
    private static <T> T reflectInvokeChannel(Channel channel, String methodStr, Class[] classes, Object... params) {

        log.info("into reflect....");
        try {
            Method method = channel.getClass().getDeclaredMethod(methodStr, classes);
            return (T) method.invoke(channel, params);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }

        return null ;
    }

}
